import cv2
import numpy as np
from .place import add_placement_bboxes
from .place import random_placement
import math

def create_box_and_random_placement(init = False, parts=None, **options):
    if init:
        add_placement_bboxes(parts, **options)
    w, h = random_placement(parts)
    return  w, h

def calc_dist_of_net(net, part):
    dist = 0
    parts = [pin.part for pin in net.pins]
    x = 0
    y = 0
    parts.remove(part)
    for p in parts:
        x += (p.bbox.ctr* p.tx).x - (part.bbox.ctr* part.tx).x
        y += (p.bbox.ctr* p.tx).y - (part.bbox.ctr* part.tx).y
        dist += math.sqrt(((p.bbox.ctr* p.tx).x - (part.bbox.ctr* part.tx).x) ** 2  + ((p.bbox.ctr* p.tx).y - (part.bbox.ctr* part.tx).y) ** 2 )
    dist = dist / len(parts)
    angle = np.arctan(((part.bbox.ctr* part.tx).y - y) / ((part.bbox.ctr* part.tx).x - x))

    return  dist, angle

def get_los_and_ol_multi_agent(
        part,
        res=20,# 分辨率
        padFlag = True,#是否启用pad，默认为开启，pad根据pins的数量决定
        padSize = 50,
        los_type= 1,
                               # board,
                               # radius,
                               # grid_comps,
                               ):
    # 找到可能相交的part集合为parts，条件为长或宽，尺寸，padsize。。。在part上搞一个画布，尺寸为1/2对角线+padSize，
    # type 0 - traditional case
    # type 1 - remove current node from the radius.
    # type 3 - cropped grid showing overlapping section
    # type 4 - cropped grid showing overlapping section and current node.

    # angle_offset = node.get_orientation()
    # res = pcbDraw_resolution()
    parts = []
    if padFlag:
        try:
            pad = padSize * len(part.pins)
        except AttributeError as e:
            pad = 0
    else :
        pad = 0
        
    for p in part.circuit.parts:##这是可能会影响的part集合
        if p == part:
            continue
        if abs((part.bbox.ctr* part.tx).x-(p.bbox.ctr* part.tx).x) < part.bbox.w / 2 + p.bbox.w / 2 + pad \
            or abs((part.bbox.ctr* part.tx).y-(p.bbox.ctr* part.tx).y) < part.bbox.h / 2 + p.bbox.h / 2 + pad :
            parts.append(p)

    if padFlag:
        x = (math.sqrt((part.bbox.h/2) ** 2 + (part.bbox.w/2) ** 2 ) + pad)  / res
        y = x
    else:
        x = (math.sqrt((part.bbox.h / 2) ** 2 + (part.bbox.w / 2) ** 2))  / res
        y = x
    # x = board.get_width() / res
    # y = board.get_height() / res
    angle_offset = 22.5 #逆时针
    # pos = node.get_pos()
    cx = x 
    cy = y 

    # if padding is not None:
    #     cx = int(pos[0]/res) + int(padding/res)
    #     cy = int(pos[1]/res) + int(padding/res)
    # else:
    #     cx = int(pos[0]/res)
    #     cy = int(pos[1]/res)

    radius = x

    if los_type in (0, 1):
        ellipse_segments_mask = np.zeros((8,int(x*2),int(y*2)), np.uint8)
        los_segments = np.zeros((8,int(x*2),int(y*2)), np.uint8)
        # overlap_segments_mask = np.zeros((8,int(x*2),int(y*2)), np.uint8)
        overlap_segments = np.zeros((8,int(x*2),int(y*2)), np.uint8)




        segment_mask_pixels = np.zeros(8)
        segment_pixels = np.zeros(8)
        overlap_mask_pixels = np.zeros(8)
        overlap_pixels = np.zeros(8)
        start = -22.5 - angle_offset
        stop = 22.5 - angle_offset

        comp_mask_self = np.zeros((int(x*2),int(y*2)), np.uint8)
        cv2.rectangle(comp_mask_self,
                      (int(cx - part.bbox.w / 2), int(cy - part.bbox.h / 2)),  # 注意这里将cx用于宽度，cy用于高度
                      (int(cx + part.bbox.w / 2), int(cy + part.bbox.h / 2)),
                      (64),
                      -1
                      )

        comp_mask_others = []
        for p in parts:# 向量+原点
            p_x_1 = ((p.bbox.ctr* part.tx).x - (part.bbox.ctr* part.tx).x - p.bbox.w /2) / res + cx
            p_y_1 = ((p.bbox.ctr* part.tx).y - (part.bbox.ctr* part.tx).y - p.bbox.h / 2) / res + cy
            p_x_2 = ((p.bbox.ctr* part.tx).x - (part.bbox.ctr* part.tx).x + p.bbox.w / 2) / res + cx
            p_y_2 = ((p.bbox.ctr* part.tx).y - (part.bbox.ctr* part.tx).y + p.bbox.h / 2) / res + cy
            comp_mask_other = np.zeros((int(x*2),int(y*2)), np.uint8)
            cv2.rectangle(comp_mask_other,# 代表其他comp
                          (int(p_x_1),int(p_y_1)),
                          (int(p_x_2),int(p_y_2)),
                          (64),
                          -1
                          )
            comp_mask_others.append(comp_mask_other)

        for i in range(8):
            cv2.ellipse(ellipse_segments_mask[i],
                        (int(cx),int(cy)),
                        (int(radius),int(radius)),
                        0,
                        start,
                        stop,
                        (64),
                        -1)
            overlap_mask_pixels[i] = np.sum(ellipse_segments_mask[i])
            segment_mask_pixels[i] = np.sum(ellipse_segments_mask[i])

            # overlap_segments_mask[i] = cv2.bitwise_and(
            #     src1=los_segments_mask[i],
            #     src2=comp_mask_self)


            # if los_type == 1:
            #     los_segments_mask[i] -= overlap_segments_mask[i]



            for j in range(0, len(parts),1):
                los_segments[i] =ellipse_segments_mask[i] - cv2.bitwise_and( \
                    src1=(cv2.bitwise_or(src1 = comp_mask_self,
                                         src2=comp_mask_others[j])),
                    src2=ellipse_segments_mask[i])
                # los_segments[i] = cv2.bitwise_or(
                #     src1=cv2.bitwise_and(src1=los_segments_mask[i],
                #                          src2=comp_mask_others[j]),
                #     src2=los_segments[i])

                overlap_segments[i] = ellipse_segments_mask[i] - los_segments[i]

            segment_pixels[i] = np.sum(los_segments[i])
            overlap_pixels[i] = np.sum(overlap_segments[i])

            start -= 45
            stop -= 45

        return segment_pixels/segment_mask_pixels, overlap_pixels/overlap_mask_pixels, ellipse_segments_mask, ellipse_segments_mask
               # los_segments_mask, overlap_segments_mask

    if los_type == 2:
        
        return

    if los_type in (3, 4):
        return
        grid = setup_empty_grid(bx=board.get_width(),
                                by=board.get_height(),
                                resolution=pcbDraw_resolution(),
                                padding=padding)

        cv2.circle(img=grid,
                    center=(cx,cy),
                    color=(64),
                    radius=radius,
                    thickness = -1 )

        grid = grid.reshape(grid.shape[0], grid.shape[1])
        grid = cv2.bitwise_and(src1=grid, src2=grid_comps[0])
        if los_type == 3:
            return grid[int(cy-radius/2-1):int(cy+radius/2+1),
                        int(cx-radius/2-1):int(cx+radius/2+1)]
        else:
            grid += grid_comps[1]
            return grid[int(cy-radius/2-1):int(cy+radius/2+1),
                        int(cx-radius/2-1):int(cx+radius/2+1)]

def compute_vector_to_group_midpoint(part):
    x = 0
    y = 0
    counter = 0
    for pin in part:
        for net in pin.nets:
            parts = [pin.part for pin in net.pins]
            parts.remove(part)
            for p in parts:
                x += (p.bbox.ctr* p.tx).x
                y += (p.bbox.ctr* p.tx).y
                counter += 1

    x = x / counter
    y = y / counter
    dist = math.sqrt(((part.bbox.ctr* part.tx).x - x) ** 2 + ((part.bbox.ctr* part.tx).y - y) ** 2)
    angle = np.arctan(((part.bbox.ctr* part.tx).y - y) / ((part.bbox.ctr* part.tx).x - x))
    return dist, angle